// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "Engine/DeveloperSettingsBackedByCVars.h"
#include "UObject/PrimaryAssetId.h"
#include "UObject/SoftObjectPath.h"
#include "LyraDeveloperSettings.generated.h"

struct FPropertyChangedEvent;

class ULyraExperienceDefinition;

/**
 * 枚举定义作弊执行的时间点
 */
UENUM()
enum class ECheatExecutionTime
{
	// 当作弊管理器被创建时执行
	OnCheatManagerCreated,

	// 当玩家拥有一个Pawn时执行
	OnPlayerPawnPossession
};

/**
 * 结构体，定义要运行的作弊命令及其执行阶段
 */
USTRUCT()
struct FLyraCheatToRun
{
	GENERATED_BODY()

	// 作弊执行的阶段
	UPROPERTY(EditAnywhere)
	ECheatExecutionTime Phase = ECheatExecutionTime::OnPlayerPawnPossession;

	// 要执行的作弊命令字符串
	UPROPERTY(EditAnywhere)
	FString Cheat;
};

/**
 * 开发者设置/编辑器作弊
 */
UCLASS(config=EditorPerProjectUserSettings, MinimalAPI)
class ULyraDeveloperSettings : public UDeveloperSettingsBackedByCVars
{
	GENERATED_BODY()

public:
	ULyraDeveloperSettings();

	//~UDeveloperSettings interface
	/**
	 * 获取设置分类名称
	 * @return 分类名称，返回项目名称
	 */
	virtual FName GetCategoryName() const override;
	//~End of UDeveloperSettings interface

public:
	// 用于在编辑器中游戏（Play in Editor）时的体验覆盖（如果未设置，将使用打开地图的世界设置中的默认值）
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, config, Category=Lyra, meta=(AllowedTypes="LyraExperienceDefinition"))
	FPrimaryAssetId ExperienceOverride;

	// 是否覆盖机器人数量
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, config, Category=LyraBots, meta=(InlineEditConditionToggle))
	bool bOverrideBotCount = false;

	// 要生成的玩家机器人数量覆盖值
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, config, Category=LyraBots, meta=(EditCondition=bOverrideBotCount))
	int32 OverrideNumPlayerBotsToSpawn = 0;

	// 是否允许玩家机器人攻击
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, config, Category=LyraBots)
	bool bAllowPlayerBotsToAttack = true;

	// 在编辑器中游戏时，是否执行完整的游戏流程，还是跳过"等待玩家"等游戏阶段？
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, config, Category=Lyra)
	bool bTestFullGameFlowInPIE = false;

	/**
	 * 即使最后一个输入设备不是游戏手柄，是否也应该播放力反馈效果？
	 * 在Lyra中的默认行为是只有当最近的输入设备是游戏手柄时才播放力反馈。
	 */
	UPROPERTY(config, EditAnywhere, Category = Lyra, meta = (ConsoleVariable = "LyraPC.ShouldAlwaysPlayForceFeedback"))
	bool bShouldAlwaysPlayForceFeedback = false;

	// 游戏逻辑是否应该在编辑器中加载装饰性背景，还是为了迭代速度而跳过它们？
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, config, Category=Lyra)
	bool bSkipLoadingCosmeticBackgroundsInPIE = false;

	// 在"编辑器中游戏"期间自动运行的作弊命令列表
	UPROPERTY(config, EditAnywhere, Category=Lyra)
	TArray<FLyraCheatToRun> CheatsToRun;
	
	// 是否应该记录通过游戏消息子系统广播的消息？
	UPROPERTY(config, EditAnywhere, Category=GameplayMessages, meta=(ConsoleVariable="GameplayMessageSubsystem.LogMessages"))
	bool LogGameplayMessages = false;

#if WITH_EDITORONLY_DATA
	/** 可通过编辑器工具栏访问的常用地图列表 */
	UPROPERTY(config, EditAnywhere, BlueprintReadOnly, Category=Maps, meta=(AllowedClasses="/Script/Engine.World"))
	TArray<FSoftObjectPath> CommonEditorMaps;
#endif
	
#if WITH_EDITOR
public:
	/**
	 * 由编辑器引擎调用，当有作弊激活时弹出提醒通知
	 */
	LYRAGAME_API void OnPlayInEditorStarted() const;

private:
	/**
	 * 应用设置
	 */
	void ApplySettings();
#endif

public:
	//~UObject interface
#if WITH_EDITOR
	/**
	 * 属性更改后处理函数
	 * @param PropertyChangedEvent 属性更改事件
	 */
	virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
	/**
	 * 配置重新加载后处理函数
	 * @param PropertyThatWasLoaded 被加载的属性
	 */
	virtual void PostReloadConfig(FProperty* PropertyThatWasLoaded) override;
	/**
	 * 属性初始化后处理函数
	 */
	virtual void PostInitProperties() override;
#endif
	//~End of UObject interface
};